package userInterface.Panels;

import logging.*;

import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;

/**
 * UI JPanel for viewing the log file.
 * @author BDS
 */
public class PanelLog extends PanelBase
{
	private static final long serialVersionUID = 1L;

	private DocumentListener logDocumentListener;
	private ActionListener buttonActionListener;
	
	private SpringLayout slLogLayout;

	private JScrollPane scpLogFile;
	private JEditorPane edpLogFile;
	private JButton btnClear;
	private JButton btnSave;
	private JButton btnCopy;
	private JButton btnRevert;

	/**
	 * Class constructor.
	 */
	public PanelLog()
	{
		logDocumentListener = new LogDocumentListener();
		buttonActionListener = new ButtonActionListener();

		slLogLayout = new SpringLayout();
		setLayout(slLogLayout);

		scpLogFile = new JScrollPane();
		scpLogFile.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		slLogLayout.putConstraint(SpringLayout.WEST, scpLogFile, 10, SpringLayout.WEST, this);
		slLogLayout.putConstraint(SpringLayout.NORTH, scpLogFile, 10, SpringLayout.NORTH, this);
		slLogLayout.putConstraint(SpringLayout.EAST, scpLogFile, -10, SpringLayout.EAST, this);
		slLogLayout.putConstraint(SpringLayout.SOUTH, scpLogFile, -100, SpringLayout.SOUTH, this);
		add(scpLogFile);

		edpLogFile = new JEditorPane();
		edpLogFile.setFont(new java.awt.Font("monospaced", 0, 12));
		scpLogFile.setViewportView(edpLogFile);

		btnClear = new JButton("Clear");
		btnClear.setMnemonic(KeyEvent.VK_L);
		btnClear.addActionListener(buttonActionListener);
		slLogLayout.putConstraint(SpringLayout.EAST, btnClear, -6, SpringLayout.EAST, this);
		slLogLayout.putConstraint(SpringLayout.NORTH, btnClear, 6, SpringLayout.SOUTH, scpLogFile);
		add(btnClear);

		btnSave = new JButton("Save");
		btnSave.setMnemonic(KeyEvent.VK_S);
		btnSave.addActionListener(buttonActionListener);
		slLogLayout.putConstraint(SpringLayout.SOUTH, btnSave, -10, SpringLayout.SOUTH, this);
		add(btnSave);

		btnCopy = new JButton("Copy");
		btnCopy.setMnemonic(KeyEvent.VK_C);
		btnCopy.addActionListener(buttonActionListener);
		slLogLayout.putConstraint(SpringLayout.EAST, btnSave, -6, SpringLayout.WEST, btnCopy);
		slLogLayout.putConstraint(SpringLayout.NORTH, btnSave, 0, SpringLayout.NORTH, btnCopy);
		slLogLayout.putConstraint(SpringLayout.SOUTH, btnCopy, -10, SpringLayout.SOUTH, this);
		add(btnCopy);

		btnRevert = new JButton("Revert");
		slLogLayout.putConstraint(SpringLayout.EAST, btnCopy, -6, SpringLayout.WEST, btnRevert);
		slLogLayout.putConstraint(SpringLayout.EAST, btnRevert, -10, SpringLayout.EAST, this);
		slLogLayout.putConstraint(SpringLayout.SOUTH, btnRevert, -10, SpringLayout.SOUTH, this);
		btnRevert.setMnemonic(KeyEvent.VK_R);
		btnRevert.addActionListener(buttonActionListener);
		add(btnRevert);

		setEditedState(false);
	}

	/**
	 * Loads the log file.
	 */
	@Override
	public void load()
	{
		try
		{
			setEditedState(false);
			edpLogFile.read(new FileReader(Logger.getLogFilePath()), null);
			edpLogFile.getDocument().addDocumentListener(logDocumentListener);
		}
		catch (Exception exception)
		{
			edpLogFile.setText("An error occurred while reading the log file: " + Logger.getLogFilePath());
		}
	}

	/**
	 * Sets the availability of the Save and Revert buttons based on the given state.
	 * @param edited True if the log file has been changed; false if it reflects the log.txt file.
	 */
	private void setEditedState(boolean edited)
	{
		btnSave.setEnabled(edited);
		btnRevert.setEnabled(edited);
	}

	/**
	 * DocumentListener for the log JEditorPane.
	 * @author BDS
	 */
	private class LogDocumentListener implements DocumentListener
	{
		/**
		 * Sets the edited state.
		 */
		@Override
		public void changedUpdate(DocumentEvent e)
		{
			setEditedState(true);
		}

		/**
		 * Sets the edited state.
		 */
		@Override
		public void insertUpdate(DocumentEvent e)
		{
			setEditedState(true);
		}

		/**
		 * Sets the edited state.
		 */
		@Override
		public void removeUpdate(DocumentEvent e)
		{
			setEditedState(true);
		}
	}

	/**
	 * ActionListener for the log JButton objects.
	 * @author BDS
	 */
	private class ButtonActionListener implements ActionListener
	{
		/**
		 * Executes specific commands based on the button pressed. 
		 * Clear - Clears the displayed log file. 
		 * Save - Saves the displayed log file.
		 * Copy - Saves a copy of the displayed log file. 
		 * Revert - Reverts all edits to the displayed log file.
		 */
		public void actionPerformed(ActionEvent actionEvent)
		{
			if (actionEvent.getActionCommand().equals(btnClear.getActionCommand()))
			{
				setEditedState(true);
				edpLogFile.setText("");
			}
			else if (actionEvent.getActionCommand().equals(btnSave.getActionCommand()))
			{
				try
				{
					setEditedState(false);
					
					new File(Logger.getLogFilePath()).delete();
					new File(Logger.getLogFilePath()).createNewFile();

					FileWriter out = new FileWriter(Logger.getLogFilePath());
					out.write(edpLogFile.getText());
					out.close();
				}
				catch (Exception exception)
				{
					Logger.logMessage("Unable to save log file :" + Logger.getLogFilePath());
					Logger.logException(exception);
				}
			}
			else if (actionEvent.getActionCommand().equals(btnCopy.getActionCommand()))
			{
				JFileChooser fileSaver = new JFileChooser(System.getProperty("user.dir"));
				if (fileSaver.showSaveDialog(((JButton) actionEvent.getSource()).getParent()) == JFileChooser.APPROVE_OPTION)
				{
					try
					{
						fileSaver.getSelectedFile().delete();
						fileSaver.getSelectedFile().createNewFile();

						FileWriter fileWriter = new FileWriter(fileSaver.getSelectedFile().getAbsolutePath());
						fileWriter.write(edpLogFile.getText());
						fileWriter.close();
					}
					catch (Exception exception)
					{
						Logger.logMessage("Unable to copy log file :" + fileSaver.getSelectedFile().getAbsolutePath());
						Logger.logException(exception);
					}
				}
			}
			else if (actionEvent.getActionCommand().equals(btnRevert.getActionCommand()))
			{
				load();
			}
		}
	}
}
